home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Font Handler / NonDatabaseShape.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  13.8 KB  |  480 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        NonDatabaseShape.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains code for the handling of shapes
  6.                         who's glyphs were not in the initial font database,
  7.                         such as those added by imaging time printing extensions
  8.  
  9.  
  10.      Version:    Technology:    Quickdraw GX 1.1.x
  11.       
  12.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  13. */
  14.  
  15. #include "GXToPSBuildConfig.h"
  16. #include <GXExceptions.h>
  17. #include "GXPrintingUniverse.h"
  18. #include "FontHandler.h"
  19. #include "FontHandlerPrivate.h"
  20. #include "FontHandlerVariations.h"
  21. #include "FontDatabase.h"
  22.  
  23. #include <GXGraphics.h>
  24. #include <MacMemory.h>
  25.  
  26. #ifdef resumeLabel
  27.     #undef resumeLabel
  28. #endif
  29. #define resumeLabel(exception)
  30.  
  31. /*******************************************************
  32.  
  33.     FHBuildShapeDbaseTags:
  34.     
  35.     Routine to build font database tags on a shape.
  36.     
  37.     Routine builds font database tags on a shape by 
  38.     flattening it.  The actual flattened information
  39.     is ignored.  We only want to get the tags built.
  40.     
  41.     Routine returns a picture that has the database tags
  42.     on it.  This is because flattening does not generate
  43.     the font database on normal shapes, just pictures.
  44.     
  45.     The picture is newly created and must therefore be disposed
  46.     of by the client of this call.
  47.     
  48. *********************************************************/
  49. static long FHSpoolProc(gxSpoolCommand command, struct gxSpoolBlock *block)
  50.     {
  51.     #pragma unused (command, block)
  52.     
  53.         /** do nothing **/
  54.         
  55.         return(0);
  56.     }
  57.  
  58. gxShape FHBuildShapeDbaseTags(gxShape theShape);
  59. gxShape FHBuildShapeDbaseTags(gxShape theShape)
  60.     {
  61.         gxSpoolBlock             theSpool;
  62.         char                            dummyBuffer[50];                // a place for gx graphics to stick data.
  63.         gxShape                        thePict;
  64.         
  65.         thePict = GXNewShape(gxPictureType);
  66.         GXSetPictureParts(thePict, 0, 0, 1, &theShape, nil, nil, nil);
  67.         
  68.         theSpool.spoolProcedure = NewgxSpoolProc(FHSpoolProc);
  69.         theSpool.buffer = dummyBuffer;
  70.         theSpool.bufferSize = 50;
  71.         
  72.         GXFlattenShape(thePict, gxFontListFlatten + gxFontGlyphsFlatten + gxFontVariationsFlatten, &theSpool);
  73.         
  74.         DisposeRoutineDescriptor(theSpool.spoolProcedure);
  75.         
  76.         return(thePict);
  77.     
  78.     }//FHBuildShapeDbaseTags
  79.  
  80.  
  81. //<FF>
  82. /******************************************
  83.  
  84.     Function:        FHRemoveBits
  85.     
  86.     Function clears bits in the destination
  87.     that are set in the source.
  88.     
  89. *******************************************/
  90. void FHRemoveBits(unsigned long *source, unsigned long *dest, long numLongs);
  91. void FHRemoveBits(unsigned long *source, unsigned long *dest, long numLongs)
  92.     {
  93.         register short            i;
  94.         
  95.         check( numLongs <= 0x0000FFFF);                /* Just for robustness in debugging build */
  96.         
  97.         for (i = numLongs - 1; i >= 0; --i)
  98.             *dest++ &= ~(*source++);
  99.         
  100.     }//FHRemoveBits
  101.     
  102.     
  103.     
  104.     
  105.     
  106. /****************************************
  107.  
  108.     Function: FHFindMatchingDBBits
  109.     
  110.     Function finds the bit array in the font
  111.     database that matches the font and the variations
  112.     specified.  This can also be used to determine the 
  113.     dbIndex of a particular variation in the database.
  114.     
  115.     fontDbase:            A font database object (Assumed locked).
  116.     theFont:                The font to search on.
  117.     axisCount:            number of variation axes.
  118.     variations:            The variations to search for.
  119.     theBits:                will return the pointer to the bit array in here, nil if no match. (pass nil if you don't care)
  120.     dbIndex:                Will return the index of the bit array in the database (pass nil if you don't care)
  121.     
  122. *****************************************/
  123. OSErr FHFindMatchingDBBits(TFontDbase fontDbase, gxFont theFont, long axisCount, gxFontVariation *variations, 
  124.                                                             unsigned long* *theBits, long *dbIndex);
  125. OSErr FHFindMatchingDBBits(TFontDbase fontDbase, gxFont theFont, long axisCount, gxFontVariation *variations, 
  126.                                                             unsigned long* *theBits, long *dbIndex)
  127.     {
  128.         OSErr                        status;
  129.         long                        nVariations;                // number of variations in the database already.
  130.         long                        idx;                                // loop counter for variations.
  131.         gxFontVariation    *dbVariations;            // variations from the database.
  132.         unsigned long        *dbBits;                        // bits from the database.
  133.         
  134.         /* Find out the number of variations in the database for this font */
  135.         
  136.         status = FontDbaseGetFontInfo(fontDbase, theFont, nil, nil, &nVariations, nil);
  137.         nrequire(status, failed_Info);
  138.  
  139.         /** Now loop through to see if we find a match **/
  140.     
  141.         if (theBits != nil)
  142.             *theBits = nil;            // no match yet.
  143.             
  144.         if (dbIndex != nil)
  145.             *dbIndex = eNotPresent;        // no match yet.
  146.         
  147.         for (idx = 1; idx <= nVariations; ++idx) {
  148.         
  149.             /** compare variations from database against the ones passed in **/
  150.  
  151.             status = FontDbaseGetGlyphBits(fontDbase, theFont, idx, &dbBits, &dbVariations);
  152.             nrequire(status, failed_Bits);
  153.             
  154.             if ( FHEqualVariations(axisCount, variations, dbVariations) ) {
  155.     
  156.                 if (theBits != nil)
  157.                     *theBits = dbBits;
  158.                     
  159.                 if (dbIndex != nil)
  160.                     *dbIndex = idx;
  161.                     
  162.                 break;
  163.                 
  164.             }//end if            
  165.         
  166.         }//end for
  167.     
  168. failed_Bits:
  169. failed_Info:
  170.  
  171.         return(status);
  172.     
  173.     }//FHFindMatchingDBBits
  174.  
  175. //<FF>
  176. /******************************************
  177.  
  178.     Function:    FHRemoveExistingGlyphBits:
  179.     
  180.     Function clears any bits in a flatFontListItem that
  181.     are already accounted for in the font database.
  182.     
  183.     hFHRec:                            font hander context handle.
  184.     fontUsage:                    the flat font list item to use for updating.
  185.     
  186. *********************************************/
  187. OSErr    FHRemoveExistingGlyphBits(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage);
  188. OSErr    FHRemoveExistingGlyphBits(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage)
  189.     {
  190.         OSErr                            status;
  191.         long                            i;
  192.         TFontDbase                fontDbase;
  193.         TFontHandlerRec        *pFHRec;
  194.         unsigned long            *existingBits;                        // bits from the database.
  195.         unsigned long            *newBits;                                    // bits from the fontUsage tag.
  196.         long                            axisCount;                                // axis count from the database.
  197.         long                            variationCount;                        // variation count from the database.
  198.         long                            nGlyphs;                                    // number of glyphs in the font.
  199.         gxFontVariation        *newVariations;                        // The new variations.
  200.         unsigned char            *p;
  201.         long                            nameLen, bitsLen;
  202.         Boolean                        lockedIt = false;                    // Have we locked the font database?
  203.         
  204.         HLock((Handle)hFHRec);
  205.         pFHRec = *hFHRec;
  206.         fontDbase = pFHRec->docDbase;
  207.         HUnlock((Handle)hFHRec);
  208.                 
  209.         /** Get database info for the font **/
  210.         
  211.         status = FontDbaseGetFontInfo(fontDbase, fontUsage->fontID, nil, nil, nil, nil);
  212.         if (status != collectionItemNotFoundErr) {
  213.         
  214.             nrequire(status, failed_GetFontInfo);
  215.             
  216.             status = FontDbaseLock(fontDbase);
  217.             nrequire(status, failed_Lock);
  218.             lockedIt = true;
  219.  
  220.             nGlyphs = fontUsage->glyphCount;
  221.             axisCount = fontUsage->axisCount;
  222.             nameLen = 4 * ( (fontUsage->length + 3) / 4);
  223.             bitsLen = 4 * ( (nGlyphs + 31) / 32);
  224.  
  225.             /*** First, clear the main bit array of any glyphs already in the database ***/
  226.             
  227.             status = FontDbaseGetGlyphBits(fontDbase, fontUsage->fontID, eMainBits, &existingBits, nil);
  228.             nrequire(status, failed_GetBits);
  229.             
  230.             p = (unsigned char*)fontUsage + nameLen;            
  231.             newBits = (unsigned long*)p;
  232.             
  233.             FHRemoveBits(existingBits, newBits, bitsLen / 4);
  234.             
  235.             /*** No do the same for all of the variations bit arrays already in the database ***/
  236.             
  237.             p += bitsLen;
  238.             
  239.             for (i = 1; i < fontUsage->variationCount; ++i) {
  240.             
  241.                 newBits = (unsigned long*)p;
  242.                 newVariations = (gxFontVariation*)(p + bitsLen);
  243.  
  244.                 status = FHFindMatchingDBBits(fontDbase, fontUsage->fontID, axisCount, newVariations, &existingBits, nil);
  245.                 nrequire(status, failed_FindMatch);
  246.             
  247.                 /*****
  248.                     If the database contained a matching variation,
  249.                     clear the bits in the fontUsage that were already in the database.
  250.                     nil return for pointer to bits means couldn't find match.
  251.                 *****/
  252.                 
  253.                 if (existingBits != nil)
  254.                     FHRemoveBits(existingBits, newBits, bitsLen / 4);
  255.                 
  256.                 p += bitsLen + axisCount * sizeof(gxFontVariation);
  257.             
  258.             }//end for
  259.                     
  260.         } else {
  261.         
  262.             /* collectionItemNotFoundErr means the font is not in the database, this is okay */
  263.             
  264.             status = noErr;
  265.         
  266.         }//end if
  267.         
  268. failed_FindMatch:
  269. failed_GetBits:
  270.  
  271.         if (lockedIt) {
  272.         
  273.             OSErr saveStatus = FontDbaseUnlock(fontDbase);
  274.             if (status != noErr)
  275.                 status = saveStatus;
  276.                 
  277.             ncheck(status);
  278.         
  279.         }//end if
  280.  
  281. failed_Lock:
  282. failed_GetFontInfo:
  283.  
  284.         return(status);
  285.     
  286.     }//FHRemoveExistingGlyphBits
  287.  
  288.  
  289. /*****************************************
  290.  
  291.     Function:        FHNonDBBuildPrinterFonts
  292.     
  293.     Function builds the printer fonts records for
  294.     the non-database shape case.  This code is quite
  295.     similar to the FHBuildPrinterFontList code in 
  296.     FontHandler.c.  Not similar enough to share code, 
  297.     however.  Here, dbIndex values must be obtained 
  298.     by calling the FindMatchingDBBits routine rather
  299.     than simply traversing the font database.  Bit arrays
  300.     come from the flatfontlistitem rather than the database
  301.     as well.
  302.     
  303. ********************************************/    
  304. OSErr FHNonDBBuildPrinterFonts(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage);
  305. OSErr FHNonDBBuildPrinterFonts(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage)
  306.     {
  307.         OSErr                                    status;
  308.         long                                    varCounter;                    // count through the variations in the fontUsage.
  309.         long                                    dbIndex;                        // dbIndex of the variation.
  310.         long                                    bitsSize;                        // size of bit array (in bytes).
  311.         long                                    variationSize;            // size of variations (in bytes)
  312.         gxFontVariation                *variations;
  313.         unsigned long                    *glyphBits;                    // glyph usage bit array.
  314.         fhFont                                snapshotID;                    // snapshot id.
  315.         unsigned char                    *p;                                    // Pointer into structure.
  316.         TFHStreamRequirements    requirements;                // Stream requirements.
  317.  
  318.         /* Test to see if we need snapshots for this font or if the font can't be streamed at all */
  319.         
  320.         status = FHGetStreamRequirements(fontUsage->fontID, (*hFHRec)->psDevice, (*hFHRec)->legalStreamTypes,
  321.                                                                     (*hFHRec)->productDescription, &requirements);
  322.         nrequire(status, failed_Test);
  323.         
  324.         /* Point p at first bit array */
  325.         
  326.         p = (unsigned char*)fontUsage;
  327.         p += sizeof(gxFlatFontListItem) + 4 * ((fontUsage->length + 3) / 4);        // add size of struct + long alligned name.
  328.         bitsSize = 4 *((fontUsage->glyphCount + 31) / 32);
  329.         variationSize = fontUsage->axisCount * sizeof(gxFontVariation);
  330.  
  331.         /* Build the appropriate printer fonts */
  332.         
  333.         if (requirements == fhNeedsSnapShots) {
  334.         
  335.             /**** Add a snapshot for each variation used ****/
  336.             
  337.             p += bitsSize;            // skip past main bits.
  338.             
  339.             for (varCounter = 0; varCounter < fontUsage->variationCount; ++varCounter) {
  340.             
  341.                 glyphBits = (unsigned long*)p;
  342.                 variations = (gxFontVariation*)(p + bitsSize);
  343.                 
  344.                 /** Get the dbIndex for this variation **/
  345.                 status = FHFindMatchingDBBits((*hFHRec)->docDbase, fontUsage->fontID, fontUsage->axisCount,
  346.                                                                                                 variations, nil, &dbIndex);
  347.                 nrequire(status, failed_FindMatch);
  348.                 
  349.                 ncheck(dbIndex == eNotPresent);            // should never happen.
  350.                 
  351.                 status = FHAddFontSnapShot(hFHRec, fontUsage->fontID, dbIndex, &snapshotID);
  352.                 nrequire(status, failed_snapshot);
  353.  
  354.                 status = FHAddPrinterFonts(hFHRec, snapshotID, glyphBits, fontUsage->glyphCount, fdbNoFontFlags);
  355.                 nrequire(status, failed_AddPrinterFont);
  356.                 
  357.                 /* Point to the next pair */
  358.                 
  359.                 p += bitsSize + variationSize;
  360.                 
  361.             }//end for
  362.         
  363.         } else {
  364.         
  365.             /**** Just add one snapshot for the main bit array ****/
  366.  
  367.             status = FHAddFontSnapShot(hFHRec, fontUsage->fontID, eMainBits, &snapshotID);
  368.             nrequire(status, failed_snapshot);
  369.             
  370.             status = FHAddPrinterFonts(hFHRec, snapshotID, (unsigned long*)p, fontUsage->glyphCount, fdbNoFontFlags);
  371.             nrequire(status, failed_AddPrinterFont);
  372.  
  373.         }//end if
  374.         
  375. failed_FindMatch:
  376. failed_snapshot:
  377. failed_AddPrinterFont:
  378. failed_Test:
  379.  
  380.         return(status);
  381.         
  382.     }//FHNonDBBuildPrinterFonts
  383.  
  384.  
  385. //<FF>
  386. /******************************************
  387.  
  388.     FHAddNonDatabaseShape:
  389.     
  390.     Routine generates printer-font records for
  391.     non-database resident glyphs from a shape.
  392.     
  393.     1.    Flatten the shape to get database tags.
  394.     
  395.     2.    For each database tag:
  396.     
  397.         2a.    Clear any glyph bits in the new tags that are already
  398.                     in the font database
  399.                     
  400.         2b.    update the database with new ones.
  401.         
  402.         2c.    Build printer-fonts for the new entries.
  403.     
  404. *******************************************/
  405. OSErr FHAddNonDatabaseShape(TFontHandlerHdl hFHRec, gxShape theShape)
  406.     {
  407.         OSErr                                status;
  408.         gxTag                                fontUsageTag;
  409.         gxFlatFontListItem    *fontUsage;
  410.         long                                nFonts;
  411.         long                                i;
  412.         TFontDbase                    docDbase;
  413.         gxShape                            thePict;
  414.         
  415.         /**** First build font database  tags ****/
  416.                 
  417.         thePict = FHBuildShapeDbaseTags(theShape);
  418.         nrequire(status = GXGetGraphicsError(nil), failed_FHBuildShapeDbaseTags);
  419.         
  420.         /** Get the font information that flattening added to the shape **/
  421.         
  422.         nFonts = GXGetShapeTags(thePict, gxFlatFontListItemTag, 1, gxSelectToEnd, nil);
  423.         
  424.         for (i = 1; (i <= nFonts) && (status == noErr); ++i) {
  425.         
  426.             /* Get a pointer to the flat font list item from the tag */
  427.             
  428.             GXGetShapeTags(thePict, gxFlatFontListItemTag, i, 1, &fontUsageTag);
  429.             fontUsage = (gxFlatFontListItem*)GXGetTagStructure(fontUsageTag, nil);
  430.             nrequire(status = GXGetGraphicsError(nil), failed_LockTag);
  431.  
  432.             /* Clear bits in the item that are already in the database */
  433.                                     
  434.             status = FHRemoveExistingGlyphBits(hFHRec, fontUsage);
  435.             nrequire(status, failed_UpdateDbase);
  436.             
  437.             /* Update the database so it contains entries for any new font/variation combinations */
  438.  
  439.             docDbase = (*hFHRec)->docDbase;
  440.             status = FontDbaseAddItem(docDbase, fontUsage, false);
  441.             nrequire(status, failed_AddItem);
  442.             
  443.             /* Build the printer fonts for this tag */
  444.             
  445.             status = FHNonDBBuildPrinterFonts(hFHRec, fontUsage);
  446.             nrequire(status, failed_BuildPrinterFonts);
  447.             
  448. failed_BuildPrinterFonts:        
  449. failed_AddItem:
  450. failed_UpdateDbase:        
  451.  
  452.             /* Unlock the tag */
  453.             
  454.             GXUnlockTag(fontUsageTag);
  455.     
  456.         }//end for
  457.  
  458. failed_LockTag:
  459.  
  460.  
  461.  
  462.         /*** Now Dispose of the database picture, we don't need it any more ***/
  463.  
  464.         GXDisposeShape(thePict);
  465.  
  466.         {
  467.             OSErr            saveStatus = GXGetGraphicsError(nil);
  468.             if (status == noErr)
  469.                 status = saveStatus;
  470.             
  471.             ncheck(status);
  472.         }
  473.         
  474. failed_FHBuildShapeDbaseTags:
  475.  
  476.         return(status);    
  477.  
  478.     }//FHAddNonDatabaseShape
  479.  
  480.